﻿using NazTek.Core;
using System.Linq;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;

namespace NazTek.Repository
{
    /// <summary>
    /// Encapsulates generic access API to database objects.
    /// </summary>
    /// <typeparam name="T">Database object type.</typeparam>
    public sealed class Repository<T> : RepositoryBase<T>, IRepository<T> where T : class, IEntity
    {
        /// <summary>
        /// Gets the expression to fetch all available records of the underlying type.
        /// </summary>
        /// <returns>The expression to fetch all available records.</returns>
        public IQueryable<T> GetAll()
        {
            return DbContext.Set<T>();
        }
        /// <summary>
        /// Executes dynamic SQL.
        /// </summary>
        /// <param name="query">The query string to execute.</param>
        /// <returns>Typed query result.</returns>
        public DbRawSqlQuery<T> ExecuteQuery(string query)
        {
            return DbContext.ExecuteQuery<T>(query);
        }
        /// <summary>
        /// Gets all available records of the underlying type.
        /// </summary>
        /// <returns>All available records.</returns>
        public List<T> GetAllList()
        {
            return GetAll().ToList();
        }
        /// <summary>
        /// Insert a record of the specified type.
        /// </summary>
        /// <param name="entity">Record to insert.</param>
        /// <returns>Number of state entries written to the database.</returns>
        public int Insert(T entity)
        {
            DbContext.Set<T>().Add(entity);
            return DbContext.SaveChanges();
        }
        /// <summary>
        /// Deletes a database record.
        /// </summary>
        /// <param name="entity">Record to delete.</param>
        /// <returns>Number of state entries written to the database.</returns>
        public int Delete(T entity)
        {
            DbContext.Set<T>().Remove(entity);
            return DbContext.SaveChanges();
        }
        /// <summary>
        /// Update a database record.
        /// </summary>
        /// <param name="entity">Record to update.</param>
        /// <returns>Number of state entries written to the database.</returns>
        public int Update(T entity)
        {
            DbContext.Entry(entity).State = EntityState.Modified;
            return DbContext.SaveChanges();
        }
        /// <summary>
        /// Updates a list of database records.
        /// </summary>
        /// <param name="entities">Records to update.</param>
        /// <returns>Number of state entries written to the database.</returns>
        public int Update(List<T> entities)
        {
            entities.ForEach(entity => DbContext.Entry(entity).State = EntityState.Modified);
            return DbContext.SaveChanges();
        }
        /// <summary>
        /// Finds database record with matching id.
        /// </summary>
        /// <param name="id">Primary key to find in database table.</param>
        /// <returns>Database table record with matching primary key id.</returns>
        public T FindById(string id)
        {
            return GetAll().FirstOrDefault(r => r.Id == id);
        }
    }
}